home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
ObserveTest
/
ObserveDispatch.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
4KB
|
165 lines
#import <objc/HashTable.h>
#import <objc/Storage.h>
#import <strings.h>
#import "ObserveDispatch.h"
@implementation ObserveDispatch
- init
{
[super init];
// Create the observers list
// The key will be the name of the method
observerTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
return self;
}
/*
** Method: initObserver:
**
** Purpose: Initialize an observer record that can then be added to the
** List of observers for an action. This is a good method for sub-classes
** to overwrite if they want to accept shorthand action names and turn
** them into something more appropriate.
*/
- initObserver:(observerrec *)anObserver withObject:(id)anObject
forAction:(char *)anAction withFilter:(char *)aFilter
{
anObserver->active = YES;
anObserver->anObject = anObject;
anObserver->action = NXCopyStringBuffer(anAction);
anObserver->filter = NXCopyStringBuffer(aFilter);
return self;
}
/*
Method: observerListForAction:
Returns a list of the observers that are watching for the given
action.
Return Value:
Returns the list of observers if there is one or nil otherwise
*/
- observerListForAction:(char *)anAction
{
id aList = nil;
aList = (id)[observerTable valueForKey:anAction];
return aList;
}
/*
Method: addObserver:forAction:withFilter:
This method is the primary interface for adding an observer to
a watch list for a given action.
Parameters:
id anObject The object that is the observer
char *actionList A comma separated list of the actions the observer
wants to watch for.
char *aFilter additional information (unused)
Return Value:
Always returns 0
*/
- (int)addObserver:(id)anObject
forAction:(char *)actionList
withFilter:(char *)aFilter
{
id aList = nil;
observerrec newobserver;
#if DBG_ADDSERVER
printf("ObserveD - addObserver:forAction: %s\n",actionList);
#endif DBG_ADDSERVER
if (!actionList || !*actionList)
return -1;
// Create an observer record
[self initObserver:&newobserver withObject:anObject
forAction:actionList withFilter:aFilter];
// Add it to the hash table
// Look for the list this belongs to
aList = [self observerListForAction:newobserver.action];
// If not found create it
if (!aList)
{
aList = [[Storage allocFromZone:[self zone]]
initCount:0
elementSize:sizeof(observerrec)
description:"{i@**}"];
// Add the new list to the table of lists
[observerTable insertKey:NXCopyStringBuffer(newobserver.action)
value:aList];
}
// Add the observer to the list
[aList addElement:&newobserver];
return NO;
}
/*
Method: addObserver:forAction:
Same as addObserver:forAction:withFilter:, but passes a blank filter
by default.
Return Value:
returns whatever addObserver:forAction:withFilter: returns
*/
- (int)addObserver:(id)anObject
forAction:(char *)actionList
{
return [self addObserver:anObject forAction:actionList withFilter:""];
}
/*
Method: forward::
Return Value:
always returns self
*/
- forward:(SEL)aSelector :(marg_list)argFrame
{
id aList = nil;
char *selectorName = sel_getName(aSelector);
// Find the list of observers for this method
// Send the message to each member of the list;
// Dispatch the message to all observers
aList = [observerTable valueForKey:selectorName];
if (aList)
{
observerrec *anObserver;
int numObservers = [aList count];
int counter = 0;
// Now we have the list of observers
// For each one of them
for (counter = 0; counter < numObservers; counter++)
{
// send out the same message
anObserver = [aList elementAt:counter];
[anObserver->anObject performv:aSelector :argFrame];
}
}
return self;
}
@end